use std::sync::Arc;

use anyhow::Error as AnyhowError;

use super::{BootstrapArtifacts, BootstrapContext, BootstrapError, BootstrapResult, BootstrapStage, ProjectProfile};

/// 引导流程观察者接口
///
/// 可用于输出日志、埋点或前端进度展示。
pub trait BootstrapObserver: Send + Sync {
    /// 阶段开始回调
    fn stage_started(
        &self,
        _profile: &ProjectProfile,
        _stage: &'static str,
    ) {
    }
    /// 阶段完成回调
    fn stage_completed(
        &self,
        _profile: &ProjectProfile,
        _stage: &'static str,
    ) {
    }
    /// 阶段失败回调
    fn stage_failed(
        &self,
        _profile: &ProjectProfile,
        _stage: &'static str,
        _error: &BootstrapError,
    ) {
    }
}

/// 引导加载器
///
/// - 维护阶段列表
/// - 顺序执行阶段并收集结果
/// - 在阶段失败时立即停止并返回错误
pub struct BootstrapLoader {
    stages: Vec<Box<dyn BootstrapStage>>,
    observers: Vec<Arc<dyn BootstrapObserver>>,
}

impl BootstrapLoader {
    /// 创建构造器
    pub fn builder() -> BootstrapLoaderBuilder {
        BootstrapLoaderBuilder::new()
    }

    /// 追加观察者
    pub fn add_observer<O>(
        &mut self,
        observer: O,
    ) where
        O: BootstrapObserver + 'static,
    {
        self.observers.push(Arc::new(observer));
    }

    /// 执行引导流程
    ///
    /// 流程说明：
    /// 1. 根据项目画像创建 BootstrapContext；
    /// 2. 依次执行每个阶段，阶段内可写入上下文；
    /// 3. 任意阶段失败将触发回调并终止；
    /// 4. 全部成功后收敛上下文为 BootstrapArtifacts。
    pub async fn bootstrap(
        &self,
        profile: ProjectProfile,
    ) -> BootstrapResult<BootstrapArtifacts> {
        let mut ctx = BootstrapContext::new(profile);
        let snapshot_profile = ctx.profile().clone();

        for stage in &self.stages {
            self.notify_started(&snapshot_profile, stage.name());
            if let Err(err) = stage.execute(&mut ctx).await {
                let stage_error = BootstrapError::stage_failure(stage.name(), AnyhowError::new(err));
                self.notify_failed(&snapshot_profile, stage.name(), &stage_error);
                return Err(stage_error);
            }
            self.notify_completed(&snapshot_profile, stage.name());
        }

        let artifacts = ctx.into_artifacts()?;
        Ok(artifacts)
    }

    fn notify_started(
        &self,
        profile: &ProjectProfile,
        stage: &'static str,
    ) {
        for observer in &self.observers {
            observer.stage_started(profile, stage);
        }
    }

    fn notify_completed(
        &self,
        profile: &ProjectProfile,
        stage: &'static str,
    ) {
        for observer in &self.observers {
            observer.stage_completed(profile, stage);
        }
    }

    fn notify_failed(
        &self,
        profile: &ProjectProfile,
        stage: &'static str,
        error: &BootstrapError,
    ) {
        for observer in &self.observers {
            observer.stage_failed(profile, stage, error);
        }
    }
}

/// 引导加载器构造器
pub struct BootstrapLoaderBuilder {
    stages: Vec<Box<dyn BootstrapStage>>,
    observers: Vec<Arc<dyn BootstrapObserver>>,
}

impl BootstrapLoaderBuilder {
    /// 创建新构造器
    pub fn new() -> Self {
        Self { stages: Vec::new(), observers: Vec::new() }
    }

    /// 链式添加阶段
    pub fn with_stage(
        mut self,
        stage: Box<dyn BootstrapStage>,
    ) -> Self {
        self.stages.push(stage);
        self
    }

    /// 直接追加阶段
    pub fn add_stage(
        &mut self,
        stage: Box<dyn BootstrapStage>,
    ) {
        self.stages.push(stage);
    }

    /// 链式追加观察者
    pub fn with_observer<O>(
        mut self,
        observer: O,
    ) -> Self
    where
        O: BootstrapObserver + 'static,
    {
        self.observers.push(Arc::new(observer));
        self
    }

    /// 构建加载器
    pub fn build(self) -> BootstrapLoader {
        BootstrapLoader { stages: self.stages, observers: self.observers }
    }
}
